#ifndef EXAMPLEEXCEPTION_H
#define EXAMPLEEXCEPTION_H

#define EXAMPLEEXCEPTION_TYPEID 10000

#define EXAMPLEEXCEPTION_INTERFACE (Type)\
    void (*Example)(Type* this);

#include "Class.h"
#include "String.h"
#include "Exception.h"

typedef struct ExampleException ExampleException;
typedef struct ExampleExceptionVirtualTable ExampleExceptionVirtualTable;

/*
    Note :
    Could be replaced by :

    struct ExceptionVirtualTable
    {
        VIRTUALTABLE_INTERFACE(, Exception)
    };
*/

struct ExampleExceptionVirtualTable
{
    unsigned long int TypeID;
    ExceptionInterface* Interface;
    ExceptionVirtualTable* AncestorTable;
    unsigned long int ReferenceCount;
    ExampleException* (*new)(unsigned long pArgsCount, va_list* pParameters);
    ExampleExceptionVirtualTable* (*Initialize)(ExampleException* this, unsigned long pArgsCount, va_list* pParameters);
    void (*Garbage)(ExampleException* this);
    unsigned long int (*TypeOf)(ExampleException* this);
    bool (*IsSameTypeThanTypeID)(ExampleException* this, unsigned long int pTypeID);
    bool (*IsKindOfTypeID)(ExampleException* this, unsigned long int pTypeID);
    bool (*IsSameTypeThan)(ExampleException* this, Class* pSource);
    bool (*IsKindOf)(ExampleException* this, Class* pSource);
};

/*
    Important : do not change the sorting

    Note :
    Could be replaced by :

    struct Exception
    {
        CLASS_INTERFACE(ExampleException, Exception)
        EXCEPTION_INTERFACE(ExampleException)
        EXAMPLEEXCEPTION_INTERFACE(ExampleException)
    };
*/
struct ExampleException
{
    ExampleExceptionVirtualTable* VirtualTable;
    void (*Constructor)(ExampleException* this, unsigned long int pArgsCount, va_list* pParameters);
    void (*Destructor)(ExampleException* this);
    ExampleException* (*Clone)(ExampleException* this);
    ExampleException* aPreviousException;
    String* aMessage;
    const Exception* const (*PreviousException)(ExampleException* this);
    const String* const (*Message)(ExampleException* this);
    bool aExample;
    void (*Example)(ExampleException* this);
};

ExampleException* ExampleExceptionNew(unsigned long pArgsCount, va_list* pParameters);
ExampleExceptionVirtualTable* ExampleExceptionInitialize(ExampleException* this, unsigned long pArgsCount, va_list* pParameters);
void ExampleExceptionConstructor(ExampleException* this, unsigned long int pArgsCount, va_list* pParameters); /* Constructor pointer of object. Called by Initialise(). Must be propagated on inherited that do not override.*/
void ExampleExceptionDestructor(ExampleException* this); /* Destructor pointer of object. Called by Garbage(). Must be propagated on inherited that do not override.*/
ExampleException* ExampleExceptionClone(ExampleException* this);
void ExampleExceptionExample(ExampleException* this);

#endif /* EXAMPLEEXCEPTION_H */
